import React, { CSSProperties } from 'react';
import './WordEdit.scss';
import {
    Editor, EditorState, RichUtils, Modifier,
    convertFromHTML, convertFromRaw, convertToRaw,
    DraftBlockType, CompositeDecorator
} from 'draft-js';
import { EditorColorPickerType, OptionBarActionType, OptionBarConfig, TypeEditorColor, TypeFontFamily, TypeFontSize, TypeInlineStyleDict } from '../../../types';
import store from '../../../redux/store';
import { adaptFontFamily, adaptFontSize2Px, colorRGB2Hex } from '../../../utils';
import CustomInlineInputEl from '../word-editor-deprecated/CustomInlineInputEl';
import { moveSelectionToEnd } from '../word-editor-deprecated/WordEditorHelper';

interface Props {
    onEditorStateChange?: (editState: EditorState) => void
}

interface State {
    editorState: EditorState
    optionBarConfig: OptionBarConfig
    currentStyleMap: any
}

type ColorStyleMap = Map<string, { color: string, hex: string }>

export default class WordEdit extends React.Component<Props, State> {
    constructor(props: Props) {
        super(props);
        this.onChange = this.onChange.bind(this);
        this.toggleLayoutVisible = this.toggleLayoutVisible.bind(this)
    };

    public editRef: any = null;
    public isEditorFocus: boolean = false;
    public containerRef: any = null;
    public containerWidthRule: string = '';
    public reduxUnSubscribeHander: any = null;
    public defaultStyleMap: Map<string, CSSProperties> = new Map();
    public styleMap: Map<string, CSSProperties> = this.defaultStyleMap;
    public backgroundColorStyleMap: ColorStyleMap = new Map();
    public textColorStyleMap: ColorStyleMap = new Map();
    public throuthLineColorStyleMap: ColorStyleMap = new Map();
    public underLineColorStyleMap: ColorStyleMap = new Map();
    public fontFamilyMap: Array<TypeFontFamily> = ['黑体', '宋体', '微软雅黑', 'Times New Roman'];
    public fontSizeMap: Array<TypeFontSize> = ['初号', '小初', '一号', '小一', '二号', '小二', '三号', '小三',
        '四号', '小四', '五号', '小五'];

    public decorator = new CompositeDecorator([
        {
            strategy(contentBlock, callback, contentState) {

                // 这个方法接收2个函数作为参数，如果第一个参数的函数执行时�返回true，
                //就会执行第二个参数函数，同时会�将匹配的�字符的起始位置和结束位置传递给第二个参数。
                contentBlock.findEntityRanges(
                    (character) => {
                        const entityKey = character.getEntity();
                        return (
                            entityKey !== null &&
                            contentState.getEntity(entityKey).getType() === 'LINK'
                        );
                    }, (...arr) => {
                        callback(...arr)
                    }
                );
            },
            component: CustomInlineInputEl
        }
    ]);

    public readonly state: Readonly<State> = {
        editorState: EditorState.createEmpty(this.decorator),
        optionBarConfig: {},
        currentStyleMap: this.defaultStyleMap
    };

    componentDidMount() {
        this.defaultStyleMap.set('SUPERSCRIPT', {
            verticalAlign: 'super',
            fontSize: '10px'
        });
        this.defaultStyleMap.set('SUBSCRIPT', {
            verticalAlign: 'sub',
            fontSize: '10px'
        })
        this.fontFamilyMap.forEach(fontFamily => {
            this.defaultStyleMap.set(fontFamily, {
                fontFamily: adaptFontFamily(fontFamily)
            })
        });
        this.fontSizeMap.forEach(fontSize => {
            this.defaultStyleMap.set(fontSize, {
                fontSize: adaptFontSize2Px(fontSize) + 'px',
                lineHeight: adaptFontSize2Px(fontSize) * 1.5 + 'px',
            })
        });
        // const wordEditorStateRawStr = localStorage.getItem('wordEditorState');
        // if (wordEditorStateRawStr) {
        //     const wordEditorState = EditorState.createWithContent(convertFromRaw(JSON.parse(wordEditorStateRawStr)),this.decorator);
        //     this.setState({ editorState: wordEditorState })
        // }
        // this.styleMap = this.defaultStyleMap;
        // this.setState({ currentStyleMap: this.styleMap })
        // const 
        this.reduxUnSubscribeHander = store.subscribe(() => {
        })
    }

    componentWillUnmount(): void {
        this.reduxUnSubscribeHander && this.reduxUnSubscribeHander();
    }

    public toggleLayoutVisible(visible: boolean) {
        if (visible) {
            this.containerRef.style.zIndex = 10;
            this.containerRef.style.display = 'flex';
        } else {
            this.containerRef.style.zIndex = -999;
            this.containerRef.style.display = 'none';
            // this.containerRef.style.width = 0;
        }
    };

    public handleChangeMainResize(siderBarWidth: number) {
        this.containerWidthRule = `calc(100% - ${394 + siderBarWidth}px)`;
        this.containerRef.style.width = this.containerWidthRule;
    };

    public onToggleBlockType(blockStyle: TypeInlineStyleDict) {
        console.log("blockStyle--->", blockStyle);
        const { editorState } = this.state;
        this.onChange(
            RichUtils.toggleInlineStyle(
                editorState,
                blockStyle
            )
        )
    };

    public onToggleInlineType(inlineStyle: TypeInlineStyleDict) {
        console.log("inlineStyle--->", inlineStyle);
        const { editorState } = this.state;
        this.onChange(
            RichUtils.toggleInlineStyle(
                editorState,
                inlineStyle
            )
        )
    };

    public onClickEditorOptionBar(actionType: OptionBarActionType) {
        console.log("onClickEditorOptionBar---->", actionType)
        const { editorState } = this.state;
        const contentState = editorState.getCurrentContent();
        const result = convertToRaw(contentState);
        console.log("result---->", result)
    };

    public onPickerEditorColor(editorColorToggleParams: TypeEditorColor) {
        console.log("onPickerEditorColor---->", editorColorToggleParams);
        const currentToggleColorKey = `${editorColorToggleParams.pickerType}-${editorColorToggleParams.color}`;
        switch (editorColorToggleParams.pickerType) {
            case 'INLINE_BACKGROUND_COLOR':
                if (!this.backgroundColorStyleMap.has(currentToggleColorKey)) {
                    this.backgroundColorStyleMap.set(currentToggleColorKey, {
                        color: editorColorToggleParams.color,
                        hex: colorRGB2Hex(editorColorToggleParams.color),
                    })
                    this.styleMap = this.generateStyleMap('INLINE_BACKGROUND_COLOR', currentToggleColorKey);
                }
                this.toggleInlineStyleColor(currentToggleColorKey)
                break;
            case 'STRIKETHROUGH_COLOR':
                if (!this.throuthLineColorStyleMap.has(currentToggleColorKey)) {
                    this.throuthLineColorStyleMap.set(currentToggleColorKey, {
                        color: editorColorToggleParams.color,
                        hex: colorRGB2Hex(editorColorToggleParams.color),
                    })
                    this.styleMap = this.generateStyleMap('STRIKETHROUGH_COLOR', currentToggleColorKey);
                }
                this.toggleInlineStyleColor(currentToggleColorKey)
                break;
            case 'TEXT_COLOR':
                if (!this.textColorStyleMap.has(currentToggleColorKey)) {
                    this.textColorStyleMap.set(currentToggleColorKey, {
                        color: editorColorToggleParams.color,
                        hex: colorRGB2Hex(editorColorToggleParams.color),
                    })
                    this.styleMap = this.generateStyleMap('TEXT_COLOR', currentToggleColorKey);
                }
                this.toggleInlineStyleColor(currentToggleColorKey)
                break;
            case 'UNDERLINE_COLOR':
                if (!this.backgroundColorStyleMap.has(currentToggleColorKey)) {
                    this.underLineColorStyleMap.set(currentToggleColorKey, {
                        color: editorColorToggleParams.color,
                        hex: colorRGB2Hex(editorColorToggleParams.color),
                    })
                    this.styleMap = this.generateStyleMap('UNDERLINE_COLOR', currentToggleColorKey);
                }
                this.toggleInlineStyleColor(currentToggleColorKey)
                break;
            default:
                break;
        }
    };

    public toggleInlineFontSize(toggledFontSize: TypeFontSize) {
        console.log("toggleInlineFontSize", this.styleMap)
        const { editorState } = this.state;
        const selection = editorState.getSelection();
        const nextContentState = Object.keys(this.fontSizeMap)
            .reduce((contentState, fontSize) => {
                return Modifier.removeInlineStyle(contentState, selection, fontSize)
            }, editorState.getCurrentContent());
        let nextEditorState = EditorState.push(
            editorState,
            nextContentState,
            'change-inline-style'
        );
        const currentStyle = editorState.getCurrentInlineStyle();
        if (selection.isCollapsed()) {
            nextEditorState = currentStyle.reduce((state, fontSize) => {
                //@ts-ignore
                return RichUtils.toggleInlineStyle(state, fontSize);
            }, nextEditorState);
        }
        if (!currentStyle.has(toggledFontSize)) {
            nextEditorState = RichUtils.toggleInlineStyle(
                nextEditorState,
                toggledFontSize
            );
        }
        this.onChange(nextEditorState)
    };

    public toggleInlineFontFamily(toggledFontFamily: TypeFontFamily) {
        const { editorState } = this.state;
        const selection = editorState.getSelection();
        const nextContentState = Object.keys(this.fontFamilyMap)
            .reduce((contentState, fontFamily) => {
                return Modifier.removeInlineStyle(contentState, selection, fontFamily)
            }, editorState.getCurrentContent());
        let nextEditorState = EditorState.push(
            editorState,
            nextContentState,
            'change-inline-style'
        );
        const currentStyle = editorState.getCurrentInlineStyle();
        if (selection.isCollapsed()) {
            nextEditorState = currentStyle.reduce((state, fontFamily) => {
                //@ts-ignore
                return RichUtils.toggleInlineStyle(state, fontFamily);
            }, nextEditorState);
        }
        if (!currentStyle.has(toggledFontFamily)) {
            nextEditorState = RichUtils.toggleInlineStyle(
                nextEditorState,
                toggledFontFamily
            );
        }
        this.onChange(nextEditorState)
    };

    toggleInlineStyleColor(toggledColor: string) {
        const { editorState } = this.state;
        const selection = editorState.getSelection();
        const nextContentState = Object.keys(this.convertStyleMap2Object(this.backgroundColorStyleMap))
            .reduce((contentState, color) => {
                return Modifier.removeInlineStyle(contentState, selection, color)
            }, editorState.getCurrentContent());
        console.log("nextContentState---->", nextContentState)
        let nextEditorState = EditorState.push(
            editorState,
            nextContentState,
            'change-inline-style'
        );
        const currentStyle = editorState.getCurrentInlineStyle();
        if (selection.isCollapsed()) {
            nextEditorState = currentStyle.reduce((state, color) => {
                //@ts-ignore
                return RichUtils.toggleInlineStyle(state, color);
            }, nextEditorState);
        }
        if (!currentStyle.has(toggledColor)) {
            nextEditorState = RichUtils.toggleInlineStyle(
                nextEditorState,
                toggledColor
            );
        }
        this.onChange(nextEditorState)
    };


    onChange(newEditorState: EditorState) {
        // console.log("onEditorStateChange---->", newEditorState)
        const { onEditorStateChange } = this.props;
        this.setState({ editorState: newEditorState });
        onEditorStateChange && onEditorStateChange(newEditorState);
    };

    onClickEditorContent() {
        if (!this.isEditorFocus) {
            const editorState = moveSelectionToEnd(this.state.editorState) //#2
            this.setState({ editorState }, () => {
                this.editRef.focus();
            })
        }
    };

    onEditorFocus() {
        this.isEditorFocus = true;
        console.log("编辑器获得焦点------>")
    }

    onEditorBlur() {
        this.isEditorFocus = false;
        console.log("编辑器失去焦点------>")
    }

    getBlockStyle(block: any) {
        switch (block.getType()) {
            case 'blockquote': return 'RichEditor-blockquote';
            default: return null;
        }
    }

    generateStyleMap(styleColorType: EditorColorPickerType, toggledColor: string) {
        console.log("generateStyleMap---->", styleColorType, toggledColor)
        let styleMap = this.styleMap;
        let colorStyleMap: ColorStyleMap = new Map();
        switch (styleColorType) {
            case 'INLINE_BACKGROUND_COLOR':
                colorStyleMap = this.backgroundColorStyleMap;
                break;
            case 'STRIKETHROUGH_COLOR':
                colorStyleMap = this.throuthLineColorStyleMap;
                break;
            case 'TEXT_COLOR':
                colorStyleMap = this.textColorStyleMap;
                break;
            case 'UNDERLINE_COLOR':
                colorStyleMap = this.underLineColorStyleMap;
                break;
            default:
                break;
        };
        Array.from(colorStyleMap).forEach(colorStyleMapEle => {
            console.log("colorKey---->1111", colorStyleMapEle[0], this.styleMap);
            const currenStyleMapEleKey = colorStyleMapEle[0];
            const currenStyleMapEleType = colorStyleMapEle[0].split('-')[0];
            if (!this.styleMap.has(currenStyleMapEleKey)) {
                switch (styleColorType) {
                    case 'INLINE_BACKGROUND_COLOR':
                        styleMap.set(toggledColor, {
                            backgroundColor: this.backgroundColorStyleMap.get(toggledColor)?.color
                        })
                        break;
                    case 'STRIKETHROUGH_COLOR':
                        styleMap.set(toggledColor, {
                            textDecorationLine: 'line-through',
                            textDecorationColor: this.throuthLineColorStyleMap.get(toggledColor)?.color
                        })
                        break;
                    case 'TEXT_COLOR':
                        styleMap.set(toggledColor, {
                            color: this.textColorStyleMap.get(toggledColor)?.color
                        })
                        break;
                    case 'UNDERLINE_COLOR':
                        styleMap.set(toggledColor, {
                            textDecorationLine: 'underline',
                            textDecorationColor: this.underLineColorStyleMap.get(toggledColor)?.color
                        })
                        break;
                    default:
                        break;
                }
            }
        });
        console.log("新生成的styleMap", styleMap)
        return styleMap;
    };

    convertStyleMap2Object(styleMap: Map<string, CSSProperties>) {
        const styleObject = Array.from(styleMap.entries()).reduce((main, [key, value]) => ({ ...main, [key]: value }), {});
        return styleObject;
    };

    customBlockRender(block: any) {
        // console.log('customBlockRender--->', block, block.getType);
        if (block.getType() == 'unstyled') {
            // return (
            //     <div style={{backgroundColor: 'red'}}>
            //         jljlkjlkjflf
            //     </div>
            // )
        }
    }

    handleAddInput() {
        const { editorState } = this.state;
        const selection = editorState.getSelection()
        const title = '500'
        const entityKey = editorState
            .getCurrentContent()
            .createEntity('LINK', 'SEGMENTED', { url: 'xxxxxxxx' })
            .getLastCreatedEntityKey()
        const contentState = Modifier.replaceText(
            editorState.getCurrentContent(),
            selection,
            `${title}`,
            editorState.getCurrentInlineStyle(),
            entityKey,
        )
        const newEditorState = EditorState.push(editorState, contentState, 'insert-characters');
        this.setState({ editorState: newEditorState })
    };



    render() {
        const { editorState, currentStyleMap } = this.state;
        const contentState = editorState.getCurrentContent();
        let className = 'word-edit-area-content';
        if (!contentState.hasText()) {
            className += ' word-edit-area-content-hide-placeholder';
        }
        return (
            <div
                ref={(c) => this.containerRef = c}
                className='word-edit-area-container content-border content-border-radius'
            >
                <div className={className} onClick={this.onClickEditorContent.bind(this)}>
                    <Editor
                        ref={(c) => this.editRef = c}
                        editorState={editorState}
                        onChange={this.onChange.bind(this)}
                        textAlignment={'left'}
                        textDirectionality={'LTR'}
                        placeholder={'输入内容...'}
                        stripPastedStyles={true}
                        onFocus={this.onEditorFocus.bind(this)}
                        onBlur={this.onEditorBlur.bind(this)}
                        //@ts-ignore
                        blockStyleFn={this.getBlockStyle.bind(this)}
                        customStyleMap={this.convertStyleMap2Object(currentStyleMap)}
                        preserveSelectionOnBlur={true}
                        blockRendererFn={this.customBlockRender.bind(this)}
                    />
                </div>
            </div>
        )
    }
}

